package org.vt.ece3574.pictoslider;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import org.vt.ece3574.pictoslider.menus.GameMenu;

import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.net.Uri;
import android.provider.MediaStore;
import android.widget.Toast;

/**
 * This class is used to store and retrieve the picture that the user wants to
 * make into a puzzle. It stores and reads Strings which represent Uri's instead
 * of Bitmaps because it is much less memory intensive.
 * 
 * @author Michael
 */
public class PictureFileManager {

	/**
	 * URL of website where images of Presidents are obtained. This portion of
	 * the URL appears before the President's number.
	 */
	private static final String PRESIDENTS_URL = "http://www.americanpresidents.org/images/";
	/**
	 * URL of website where images of Presidents are obtained. This portion of
	 * the URL appears after the President's number.
	 */
	private static final String PRESIDENTS_URL_PART2 = "_150.gif";
	/**
	 * Default string to store when someone tries to write a null Uri to the
	 * Picture File. Necessary because passing a null string to the
	 * ObjectInputStream throws an exception.
	 */
	private static final String CASE_DEFAULT = "poo";

	/**
	 * File name for the stored string.
	 */
	public static final String PICTURE_FILE = "PuzzlePhoto";

	/**
	 * The application's context. Needed to store to internal storage.
	 */
	private Context context;

	/**
	 * Constructor for the class.
	 * 
	 * @param c
	 *            - The application context.
	 */
	public PictureFileManager(Context c) {
		context = c;
	}

	/**
	 * Uses a seperate thread to store a String representing the Uri in u. If u
	 * is null, it stores the string "poo" instead.
	 * 
	 * @param u
	 *            - A Uri pointing to a picture to be made into a puzzle, or
	 *            null if the default picture is to be used instead.
	 */
	public void write(final Uri u) {
		Thread t = new Thread(new Runnable() {
			public void run() {
				ObjectOutputStream oos;
				String writeMe = CASE_DEFAULT;
				if (u != null) {
					writeMe = u.toString();
				}
				try {
					oos = new ObjectOutputStream(context.openFileOutput(
							PICTURE_FILE, Context.MODE_PRIVATE));
					oos.writeObject(writeMe);
					oos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		});
		t.start();
	}

	/**
	 * Reads a String from internal storage, and converts this string into a Uri
	 * which is then converted to a Bitmap and returned to the user. If the Uri
	 * cannot be resolved, the method simply returns the default picture.
	 * 
	 * @return The image corresponding to the String stored in internal storage,
	 *         or the default image if the string cannot be resolved.
	 */
	public Bitmap read() {
		ObjectInputStream ois = null;
		Uri u = null;
		// Retrieve the Uri
		try {
			ois = new ObjectInputStream(context.openFileInput(PICTURE_FILE));
			String temp = (String) ois.readObject();
			if (temp != null)
				u = Uri.parse(temp);
			ois.close();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}

		// Retrieve the Bitmap
		if (u != null && !(u.toString().contentEquals(CASE_DEFAULT))
				&& !(u.toString().contentEquals(GameMenu.PRESIDENTS)))
			try {
				int orientation = getOrientation(context, u);
				Bitmap temp = Bitmap.createScaledBitmap(
						MediaStore.Images.Media.getBitmap(
								context.getContentResolver(), u), 300, 300,
						true);
				if (orientation > 0) {
					Matrix matrix = new Matrix();
					matrix.postRotate(orientation);
					return Bitmap.createBitmap(temp, 0, 0, temp.getWidth(),
							temp.getHeight(), matrix, true);
				}
				return temp;
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}

		if (u.toString().contentEquals(GameMenu.PRESIDENTS)) {
			PresidentsNetworkRunnable r = new PresidentsNetworkRunnable();
			Thread t = new Thread(r);
			t.start();
			while (t.isAlive()) {
			}
			if (r.image != null)
				return r.image;
			Toast.makeText(context, "Please check your internet connection.",
					Toast.LENGTH_LONG).show();
		}
		return BitmapFactory.decodeResource(context.getResources(),
				R.drawable.smiley_face);
	}

	/**
	 * Returns an integer describing the orientation of the image pointed to by
	 * photoUri.
	 * 
	 * @param context
	 *            - The application context
	 * @param photoUri
	 *            - The Uri of the image.
	 * @return The orientation of the image.
	 */
	private static int getOrientation(Context context, Uri photoUri) {
		/* it's on the external media. */
		Cursor cursor = context.getContentResolver().query(photoUri,
				new String[] { MediaStore.Images.ImageColumns.ORIENTATION },
				null, null, null);

		if (cursor == null) {
			return -1;
		}
		if (cursor.getCount() != 1) {
			return -1;
		}

		cursor.moveToFirst();
		return cursor.getInt(0);
	}

	private class PresidentsNetworkRunnable implements Runnable {
		public Bitmap image;

		public void run() {
			int presNum = (int) (Math.random() * 43.0) + 1;
			String leadingZero = "";
			if (presNum < 10)
				leadingZero = "0";
			String webAddress = PRESIDENTS_URL + leadingZero + presNum
					+ PRESIDENTS_URL_PART2;
			try {
				URL url = new URL(webAddress);
				InputStream input = url.openStream();
				image = BitmapFactory.decodeStream(input);
				input.close();
			} catch (MalformedURLException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

}
